package org.naxx.security.model.impl.expression;

import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

import javax.xml.stream.XMLEventFactory;
import javax.xml.stream.XMLEventWriter;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.events.Attribute;
import javax.xml.stream.events.XMLEvent;

import org.naxx.security.expression.Node;
import org.naxx.security.expression.Node.NodeType;
import org.naxx.security.util.FileSystemUtil;

/**
 * Utility class which writes expression tree into XML
 * format easily readable by humans. For debugging purposes
 * only.
 */
public final class ExpressionSerializer {

	public void serialize(Node root, OutputStream os) throws Exception {
		XMLOutputFactory outFactory = XMLOutputFactory.newInstance();
		XMLEventWriter writer = null;
		try {
			writer = outFactory.createXMLEventWriter(os);
			XMLEventFactory eventFactory = XMLEventFactory.newInstance();
			this.traverse(root, writer, eventFactory);
		} finally {
			FileSystemUtil.release(writer);
		}
	}
	
	void traverse(Node node, XMLEventWriter writer, XMLEventFactory eventFactory) throws Exception {
		List<Attribute> attributes = new ArrayList<Attribute>(3);
		attributes.add(eventFactory.createAttribute("value", 
				(!node.getNodeType().equals(NodeType.LEAF ) ? "" : 
					node.getValueHolder().getValue().toString())));
		attributes.add(eventFactory.createAttribute("function", 
				(node.getFunctionType() == null ? "" : node.getFunctionType().getUri())));
		attributes.add(eventFactory.createAttribute("type", node.getNodeType().name()));
		XMLEvent startElement = eventFactory.createStartElement("", "", "node", attributes.iterator(), null);
		writer.add(startElement);
		if(node.getChildren() != null && node.getChildren().size() > 0) {
			for(Node n : node.getChildren()) {
				traverse(n, writer, eventFactory);
			}
		}
		XMLEvent endElement = eventFactory.createEndElement("", "", "node");
		writer.add(endElement);
		writer.flush();
	}
}
